﻿using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.Logging;
using Newtonsoft.Json;
using ST.Common.Data;
using ST.Common.Util;
using ST.Common.Util.Model;
using ST.Common.Util.Mvc;
using ST.Buz.Base;
using ST.Buz.Base.Entity;
using System;
using System.Collections.Generic;
using System.Linq;
using Microsoft.AspNetCore.Mvc.Rendering;
using Microsoft.Data.SqlClient;
using ST.Buz.Base.ViewModel;
using ST.Buz.Base.Enums;

namespace ST.Buz.Service
{
	public partial interface IServiceSysRole
	{
		/// <summary>
		/// 获取角色列表
		/// </summary>
		/// <returns></returns>
		List<SelectListItem> GetRoleSelectListItems(List<int> selected = null);

		/// <summary>
		/// 获取角色名称
		/// </summary>
		/// <param name="roles"></param>
		/// <returns></returns>
		List<string> GetNames(List<int> roles);

		/// <summary>
		/// 获取角色查看时的详细信息
		/// </summary>
		/// <param name="id"></param>
		/// <param name="sessionCurrent"></param>
		/// <returns></returns>
		Sys_Role GetViewDetail(int id, UserSession sessionCurrent);

		/// <summary>
		/// 获取角色编辑时的详细信息
		/// </summary>
		/// <param name="id"></param>
		/// <param name="sessionCurrent"></param>
		/// <returns></returns>
		Sys_Role GetEditDetail(int id, UserSession sessionCurrent);

		/// <summary>
		/// 获取角色相关的模块信息
		/// </summary>
		/// <param name="id"></param>
		/// <param name="sessionCurrent"></param>
		/// <returns></returns>
		VM_Sys_RoleModule GetRoleModules(int id, UserSession sessionCurrent);

		/// <summary>
		/// 通过编号查询角色信息
		/// </summary>
		/// <param name="code"></param>
		/// <returns></returns>
		Sys_Role GetByCode(string code);

		/// <summary>
		/// 删除角色
		/// </summary>
		/// <param name="id"></param>
		/// <param name="sessionCurrent"></param>
		/// <returns></returns>
		bool Delete(int id, UserSession sessionCurrent);

		/// <summary>
		/// 批量删除角色
		/// </summary>
		/// <returns></returns>
		bool BatchDelete(int[] ids, UserSession sessionCurrent);

		/// <summary>
		/// 检验角色编码是否可用
		/// </summary>
		/// <param name="id"></param>
		/// <param name="sessionCurrent"></param>
		/// <returns></returns>
		bool ValidateCode(int id, string code, UserSession sessionCurrent);

		/// <summary>
		/// 分页列表
		/// </summary>
		PageData GetPageList(VMS_Sys_Role searchModel);

		/// <summary>
		/// 新增或修改保存
		/// </summary>
		int AddOrUpdate(Sys_Role model, UserSession sessionCurrent);
	}

	public partial class ServiceSysRole
	{
		private readonly IServiceSysLog serviceSysLog;
		private readonly IServiceSysTableLog serviceSysTableLog;
		private readonly IServiceSysModule serviceSysModule;

		public ServiceSysRole(BuzContext ctx,
			IServiceSysModule _serviceSysModule,
			IServiceSysLog _serviceSysLog,
			IServiceSysTableLog _serviceSysTableLog,
			ILogger<ServiceSysRole> log)
		{
			serviceSysModule = _serviceSysModule;
			serviceSysLog = _serviceSysLog;
			serviceSysTableLog = _serviceSysTableLog;

			context = ctx;
			logger = log;
		}

		/// <summary>
		/// 
		/// </summary>
		/// <returns></returns>
		public List<SelectListItem> GetRoleSelectListItems(List<int> selected = null)
		{
			var query = from m in context.SysRole
						select m;
			List<SelectListItem> lst = new List<SelectListItem>();
			if (selected == null || selected.Count == 0)
			{
				foreach (var m in query.AsNoTracking())
				{
					SelectListItem item = new SelectListItem()
					{
						Value = m.ID.ToString(),
						Text = m.Name.ToString()
					};
					lst.Add(item);
				}
			}
			else
			{
				foreach (var m in query.AsNoTracking())
				{
					SelectListItem item = new SelectListItem()
					{
						Value = m.ID.ToString(),
						Text = m.Name.ToString(),
						Selected = selected.Contains(m.ID)
					};
					lst.Add(item);
				}
			}
			return lst;
		}

		/// <summary>
		/// 获取角色名称
		/// </summary>
		/// <param name="roles"></param>
		/// <returns></returns>
		public List<string> GetNames(List<int> roles)
		{
			if (roles == null || roles.Count == 0)
			{
				return null;
			}
			var query = from m in context.SysRole
						where roles.Contains(m.ID)
						select m.Name;
			return query.ToList();
		}

		/// <summary>
		/// 获取角色查看时的详细信息
		/// </summary>
		/// <param name="id"></param>
		/// <param name="sessionCurrent"></param>
		/// <returns></returns>
		public Sys_Role GetViewDetail(int id, UserSession sessionCurrent)
		{
			Sys_Role model = null;
			try
			{
				model = context.SysRole.SingleOrDefault(m => m.ID == id);
				if (model == null)
				{
					throw new BuzException("参数有误");
				}
			}
			catch (ArgumentException ex)
			{
				throw ex;
			}
			catch (Exception ex)
			{
				logger.LogError(ex.InnerException ?? ex, "获取对象信息出错");
				throw new BuzException("获取对象信息失败，" + (ex.InnerException != null ? ex.InnerException.Message : ex.Message));
			}
			return model;
		}

		/// <summary>
		/// 获取角色编辑时的详细信息
		/// </summary>
		/// <param name="id"></param>
		/// <param name="sessionCurrent"></param>
		/// <returns></returns>
		public Sys_Role GetEditDetail(int id, UserSession sessionCurrent)
		{
			return GetViewDetail(id, sessionCurrent);
		}

		/// <summary>
		/// 获取角色相关的模块信息
		/// </summary>
		/// <param name="id"></param>
		/// <param name="sessionCurrent"></param>
		/// <returns></returns>
		public VM_Sys_RoleModule GetRoleModules(int id, UserSession sessionCurrent)
		{
			try
			{
				VM_Sys_RoleModule vm = new VM_Sys_RoleModule();
				vm.Actions = (from ra in context.SysRoleAction
							  where ra.RoleID == id
							  select ra.ActionID).ToArray();
				vm.Modules = serviceSysModule.GetAllVisibleModuleServicesAndActions();
				return vm;
			}
			catch (ArgumentException ex)
			{
				throw ex;
			}
			catch (Exception ex)
			{
				logger.LogError(ex.InnerException ?? ex, "获取对象信息出错");
				throw new BuzException("获取对象信息失败，" + (ex.InnerException != null ? ex.InnerException.Message : ex.Message));
			}
		}

		/// <summary>
		/// 通过编号查询角色信息
		/// </summary>
		/// <param name="code"></param>
		/// <returns></returns>
		public Sys_Role GetByCode(string code)
		{
			Sys_Role model = null;
			try
			{
				if (string.IsNullOrEmpty(code))
				{
					throw new BuzException("角色编码不能为空");
				}
				model = context.SysRole.SingleOrDefault(m => m.Code == code);
			}
			catch (BuzException ex)
			{
				throw ex;
			}
			catch (Exception ex)
			{
				logger.LogError(ex.InnerException ?? ex, "获取对象信息出错");
				throw new BuzException("获取对象信息失败，" + (ex.InnerException != null ? ex.InnerException.Message : ex.Message));
			}
			return model;
		}

		/// <summary>
		/// 删除具体操作
		/// </summary>
		/// <param name="id"></param>
		/// <param name="ip"></param>
		/// <param name="dtNow"></param>
		/// <param name="sessionCurrent"></param>
		protected void DeleteWithinTrans(int id, string ip, DateTime dtNow, UserSession sessionCurrent)
		{
			var modelOld = Get(id, true);

			if (modelOld.Reserved)
			{
				throw new BuzException("系统保留角色不允许删除");
			}
			if (modelOld.Freezed)
			{
				throw new BuzException("该角色不允许修改");
			}
			SqlParameter[] paras = new SqlParameter[]{
				new SqlParameter("@RoleID",id)
			};
			//删除角色相关功能配置
			context.Database.ExecuteSqlRaw("DELETE FROM Sys_RoleAction WHERE RoleID=@RoleID", paras);
			//删除用户相关角色
			context.Database.ExecuteSqlRaw("DELETE FROM Sys_UserRole WHERE RoleID=@RoleID", paras);

			////其他扩展
			//onDelete(id);

			Delete(modelOld);

			serviceSysLog.Add(sessionCurrent, ip, $"删除角色信息，原信息：", modelOld, dtNow);
		}

		/// <summary>
		/// 删除角色
		/// </summary>
		/// <param name="id"></param>
		/// <param name="sessionCurrent"></param>
		/// <returns></returns>
		public bool Delete(int id, UserSession sessionCurrent)
		{
			bool success = false;
			try
			{
				//if (logger.IsEnabled(LogLevel.Debug))
				//{
				//	logger.LogDebug($"参数->id:{id}，state:{state}，remark:{remark}");
				//}
				if (sessionCurrent == null)
				{
					throw new BuzException("用户会话不能为空");
				}

				using (var trans = context.Database.BeginTransaction())
				{
					try
					{
						#region 事务具体操作
						DateTime dtNow = DateTime.Now;
						string ip = GetRequestIP();

						DeleteWithinTrans(id, ip, dtNow, sessionCurrent);
						#endregion

						trans.Commit();
					}
					catch (Exception ex)
					{
						trans.Rollback();
						throw ex.InnerException ?? ex;
					}
				}

				success = true;
			}
			catch (BuzException ex)
			{
				throw ex;
			}
			catch (Exception ex)
			{
				logger.LogError(ex.InnerException ?? ex, "删除角色出错");
				throw new BuzException("删除角色失败，" + (ex.InnerException != null ? ex.InnerException.Message : ex.Message));
			}
			return success;
		}

		/// <summary>
		/// 批量删除角色
		/// </summary>
		/// <returns></returns>
		public bool BatchDelete(int[] ids, UserSession sessionCurrent)
		{
			bool success = false;
			try
			{
				//if (logger.IsEnabled(LogLevel.Debug))
				//{
				//	logger.LogDebug($"参数->id:{id}，state:{state}，remark:{remark}");
				//}
				if (sessionCurrent == null)
				{
					throw new BuzException("用户会话不能为空");
				}

				if (ids == null || ids.Length == 0)
				{
					throw new BuzException("参数不能为空");
				}

				using (var trans = context.Database.BeginTransaction())
				{
					try
					{
						#region 事务具体操作
						DateTime dtNow = DateTime.Now;
						string ip = GetRequestIP();

						foreach (int id in ids)
						{
							DeleteWithinTrans(id, ip, dtNow, sessionCurrent);
						}
						#endregion

						trans.Commit();
					}
					catch (Exception ex)
					{
						trans.Rollback();
						throw ex.InnerException ?? ex;
					}
				}

				success = true;
			}
			catch (BuzException ex)
			{
				throw ex;
			}
			catch (Exception ex)
			{
				logger.LogError(ex.InnerException ?? ex, "批量删除角色出错");
				throw new BuzException("批量删除角色失败，" + (ex.InnerException != null ? ex.InnerException.Message : ex.Message));
			}
			return success;
		}

		/// <summary>
		/// 检验角色编码是否可用
		/// </summary>
		/// <param name="id"></param>
		/// <param name="sessionCurrent"></param>
		/// <returns></returns>
		public bool ValidateCode(int id, string code, UserSession sessionCurrent)
		{
			try
			{
				//if (logger.IsEnabled(LogLevel.Debug))
				//{
				//	logger.LogDebug($"参数->id:{id}，state:{state}，remark:{remark}");
				//}
				if (sessionCurrent == null)
				{
					throw new BuzException("用户会话不能为空");
				}
				if (string.IsNullOrEmpty(code))
				{
					throw new BuzException("登录账号不能为空");
				}
				if (id == 0)
				{
					return !context.SysRole.Any(m => m.Code == code);
				}
				var lst = context.SysRole.Where(m => m.Code == code).AsNoTracking().ToList();
				if (lst.Count == 0)
				{
					return true;
				}
				foreach (var i in lst)
				{
					if (i.ID != id)
					{
						return false;
					}
				}

				return true;
			}
			catch (BuzException ex)
			{
				throw ex;
			}
			catch (Exception ex)
			{
				logger.LogError(ex.InnerException ?? ex, "检验登录账号是否可用出错");
				throw new BuzException("检验登录账号是否可用失败，" + (ex.InnerException != null ? ex.InnerException.Message : ex.Message));
			}
		}

		/// <summary>
		/// 分页列表
		/// </summary>
		public PageData GetPageList(VMS_Sys_Role searchModel)
		{
			PageData result = null;
			try
			{
				searchModel.Validate();

				var query = (from u in context.SysRole
							 select u).AsNoTracking();
				if (!string.IsNullOrWhiteSpace(searchModel.name))
				{
					query = query.Where(m => EF.Functions.Like(m.Name, "%" + searchModel.name + "%"));
				}
				if (!string.IsNullOrEmpty(searchModel.code))
				{
					query = query.Where(m => m.Code == searchModel.code);
				}
				if (searchModel.state.HasValue)
				{
					query = query.Where(m => m.StateNow == searchModel.state.Value);
				}
				if (searchModel.reserved.HasValue)
				{
					query = query.Where(m => m.Reserved == searchModel.reserved.Value);
				}
				if (searchModel.freezed.HasValue)
				{
					query = query.Where(m => m.Freezed == searchModel.freezed.Value);
				}

				switch (searchModel.sortby)
				{
					case "Code":
						////数据库分页，不支持多表
						//query = query.OrderByDescending(e => EF.Property<object>(e, sortOrder));
						////内存分页
						////query = query.OrderByDescending(e => e.GetType().GetProperty(sortOrder).GetValue(e, null));
						query = searchModel.orderby == Common.Util.Mvc.SortOrder.Ascending ? query.OrderBy(e => e.Code) : query.OrderByDescending(e => e.Code);
						break;
					case "Name":
						query = searchModel.orderby == Common.Util.Mvc.SortOrder.Ascending ? query.OrderBy(e => e.Name) : query.OrderByDescending(e => e.Name);
						break;
					case "StateNow":
						query = searchModel.orderby == Common.Util.Mvc.SortOrder.Ascending ? query.OrderBy(e => e.StateNow) : query.OrderByDescending(e => e.StateNow);
						break;
					default:
						query = query.OrderBy(e => e.Sort).ThenBy(e => e.ID);
						break;
				}
				result = new PageData(searchModel.pnum.Value, searchModel.psize.Value);
				result.Load(query);
			}
			catch (BuzException ex)
			{
				throw ex;
			}
			catch (Exception ex)
			{
				logger.LogError(ex.InnerException ?? ex, "获取分页数据出错");
				throw new BuzException("获取分页数据失败，" + (ex.InnerException != null ? ex.InnerException.Message : ex.Message));
			}
			return result;
		}

		/// <summary>
		/// 新增或修改保存
		/// </summary>
		public int AddOrUpdate(Sys_Role model, UserSession sessionCurrent)
		{
			try
			{
				if (sessionCurrent == null)
				{
					throw new BuzException("用户会话不能为空");
				}
				if (model == null)
				{
					throw new BuzException("参数不能为空");
				}

				using (var trans = context.Database.BeginTransaction())
				{
					try
					{
						#region 事务具体操作
						DateTime dtNow = DateTime.Now;
						string ip = GetRequestIP();

						if (model.ID > 0)
						{
							var modelOld = Get(model.ID, true);
							if (modelOld.Freezed)
							{
								throw new BuzException("该角色不允许修改");
							}
							if (context.SysRole.Any(m => m.OrgID == model.OrgID && (m.Code == model.Code && m.ID != model.ID || m.Name == model.Name && m.ID != model.ID)))
							{
								throw new BuzException("角色名称、编码不能重复");
							}

							var lstRoleActionOld = (from d in context.SysRoleAction
													where d.RoleID == model.ID
													select d.ActionID).ToList();
							IEnumerable<int> lstDelete = null;
							IEnumerable<int> lstAdd = null;
							if (model.ModuleConfig == null ||
								model.ModuleConfig.Actions == null ||
								model.ModuleConfig.Actions.Length == 0)
							{
								lstDelete = lstRoleActionOld;
							}
							else
							{
								lstDelete = lstRoleActionOld.Except(model.ModuleConfig.Actions);//找出删掉的
								lstAdd = model.ModuleConfig.Actions.Except(lstRoleActionOld);
							}
							if (lstDelete != null)
							{
								foreach (var d in lstDelete)
								{
									SqlParameter[] paras0 = new SqlParameter[]{
										new SqlParameter("@RoleID",model.ID),
										new SqlParameter("@ActionID",d)
									};
									context.Database.ExecuteSqlRaw("DELETE FROM Sys_RoleAction WHERE RoleID=@RoleID AND ActionID=@ActionID", paras0);
								}
							}
							if (lstAdd != null)
							{
								foreach (var a in lstAdd)
								{
									Sys_RoleAction roleAction = new Sys_RoleAction();
									roleAction.ActionID = a;
									roleAction.RoleID = model.ID;
									context.SysRoleAction.Add(roleAction);
								}
								context.SaveChanges();
							}

							SqlParameter[] paras1 = new SqlParameter[]{
								new SqlParameter("@RoleID",model.ID)
							};
							//更新角色功能编码
							context.Database.ExecuteSqlRaw("UPDATE Sys_RoleAction SET ActionCode = Sys_ModuleAction.Code FROM Sys_ModuleAction WHERE Sys_RoleAction.RoleID = @RoleID AND Sys_RoleAction.ActionID = Sys_ModuleAction.ID", paras1);

							if (modelOld.Reserved)//系统保留有些信息不允许修改
							{
								model.Name = modelOld.Name;
								model.Code = modelOld.Code;
								model.Comment = modelOld.Comment;
							}
							Update(model);

							//serviceSysTableLog.Add(sessionCurrent, TableCode.Sys_Role, model.ID, ip, "修改角色信息，新信息如下：", model, dtNow, true);
						}
						else
						{
							if (context.SysRole.Any(m => (m.Code == model.Code || m.Name == model.Name) && m.OrgID == model.OrgID))
							{
								throw new BuzException("角色名称、编码不能重复");
							}
							model.AddDate = dtNow;
							model.AddManID = sessionCurrent.UserID;
							model.AddManName = sessionCurrent.UserName;
							model.StateNow = (int)RoleState.正常;
							model.OrgID = sessionCurrent.OrgID;
							Add(model);

							if (model.ModuleConfig != null
								&& model.ModuleConfig.Actions != null
								&& model.ModuleConfig.Actions.Length > 0)
							{
								for (int i = 0; i < model.ModuleConfig.Actions.Length; i++)
								{
									Sys_RoleAction roleAction = new Sys_RoleAction();
									roleAction.ActionID = model.ModuleConfig.Actions[i];
									roleAction.RoleID = model.ID;
									context.SysRoleAction.Add(roleAction);
								}
								context.SaveChanges();

								SqlParameter[] paras = new SqlParameter[]{
									new SqlParameter("@RoleID",model.ID)
								};
								//更新角色功能编码
								context.Database.ExecuteSqlRaw("UPDATE Sys_RoleAction SET ActionCode = Sys_ModuleAction.Code FROM Sys_ModuleAction WHERE Sys_RoleAction.RoleID = @RoleID AND Sys_RoleAction.ActionID = Sys_ModuleAction.ID", paras);
							}
						}

						#endregion

						trans.Commit();

						return model.ID;
					}
					catch (Exception ex)
					{
						trans.Rollback();
						throw ex.InnerException ?? ex;
					}
				}
			}
			catch (BuzException ex)
			{
				throw ex;
			}
			catch (Exception ex)
			{
				logger.LogError(ex.InnerException ?? ex, "保存对象信息出错");
				throw new BuzException("数据库保存失败，" + (ex.InnerException != null ? ex.InnerException.Message : ex.Message));
			}
		}
	}
}